package org.app.appjson.adapter;

import org.app.appjson.exception.AppJsonException;
import org.app.appjson.reader.JsonLexer;
import org.app.appjson.reader.JsonToken;
import org.app.appjson.reader.ReadHandler;
import org.app.appjson.writer.WriteHandler;

import java.util.Collection;

/**
 * 集合类型适配器
 * @param <E> 类型参数
 * @author lizhongsi
 * @version 1.0
 * @since 1.0
 */
public final class CollectionAdapter<E> implements TypeAdapter {

    /* 集合适配器读方法 */
    public static <E> Collection<E> read(ReadHandler handler) throws AppJsonException {
        JsonLexer lexer = handler.getLexer();
        if (lexer.peek().getType() == JsonToken.NULL) {
            lexer.next();
            return null;
        }

        if (lexer.peek().getType() != JsonToken.BEGIN_ARRAY) {// 必须以'{'开始
            throw new AppJsonException("Collection must start with BEGIN_ARRAY.");
        }
        lexer.next(); //消费'['字符
        Collection<E> collection = handler.newInstance(); //创建集合对象
        Class<?> classOfElement = handler.getObjectClass(null); //保存“集合中的元素”的类型
        while (lexer.peek().getType() != JsonToken.END_ARRAY) {
            E element = (E) handler.doRead(classOfElement); //根据元素类型创建元素对象
            collection.add(element);
            if (lexer.peek().getType() == JsonToken.SEP_COMMA) { //消费两个元素之间的逗号','
                lexer.next();
            }
        }
        if (lexer.peek().getType() != JsonToken.END_ARRAY) {// 必须以'}'结束
            throw new AppJsonException("Collection must end with END_ARRAY.");
        }
        lexer.next(); //消费']'字符
        return collection;
    }

    /* 集合适配器写方法 */
    public static <E> void write(WriteHandler handler) throws AppJsonException {
        Object object = handler.getObject();
        if (object == null) {
            handler.write("null");
            return;
        }
        if (!(object instanceof Collection)) {
            throw new AppJsonException("Object is not Collection type.");
        }
        Collection<E> collection = (Collection<E>) handler.getObject();
        boolean isArrayEmpty = true;
        handler.write("[");
        for (E element : collection) {
            if (!isArrayEmpty) {//数组不空则拼一个','
                handler.write(",");
            }
            handler.doWrite(element);
            isArrayEmpty = false;
        }
        handler.write("]");
    }
}